
/* this file include function about how a AST coverts to a dot graph
 * language
 *
 * Author:	JieJing Zhang	kzjeef@gmail.com
 * Date:	May 2 2008
 *
 * */


 
#include "globals.h"
#include "dot.h"
#include <assert.h>
#include <string.h>


static int draw_tree(tree);
static int draw_node(tree, tree);
static int adorn_node(tree);
static int draw_relationship(tree from_node, tree to_node) ;

static FILE *DOT_FILE = 0;

void tree2dot(dotattr *attr,char *title, tree t, FILE *out) {
	/* firstly, print the graph like 'digraph G {' to the file
	 * title should be the file's name like 'tree.hpp'
	 */
	assert(t);
	if (!out)
		out = stdout;
	if (!title)				 
		title = "anonymous";
	else { 			/* claen bad char like '.' '/' replace with '_'
				 * these char dot language not accept*/
		char *str = strdup(title);
		
		char *cp;
		title = str;
		for (cp = str; *cp != 0; cp++) {
			if(*cp == '\\'
			   || *cp == '/'
			   || *cp == '.'
			   || *cp == '#')
				
				*cp = '_';
		}
	}
					

	DOT_FILE = out;
	
	char buf[BUFSIZE];
	char *tp = buf;
		
	fprintf(DOT_FILE, "digraph %s {\n",title);
	
	/* and adding some graph's attributes such as 'size' or
	 * something else */

	/* ADDING LATER */
		
	/* and then, according the syntax tree put the relationship
	 * between every class and derived class  */

	draw_tree(t);

	/* TODO: in above step, decorate the graph via the tree
	 *  node's attributes */

	/* at last, output end tail of the dot language like '};' */
	tp += fprintf(DOT_FILE, "};\n");
}


static
int draw_tree(tree t) {
	tree t1 = t;
	assert(DOT_FILE);
	assert(t);


	for(; t1 != 0; t1 = t1->sibling) {
		if (t1->class_attr._alone == _TRUE) {
			draw_node(t1,0);
		} else {
			int i;
			draw_node(t1,0); /* print t1's attributes */
			
			for (i = 0; i < MAXCHILDREN; i++) {
				if (t1->child[i] == 0)
					continue;
				draw_node( t1->child[i],t1);
			}
		}
	}
	return 0;
}

int draw_node(tree from_node , tree to_node) {
	adorn_node(from_node);
	fprintf(DOT_FILE,";\n");
//	adorn_node(to_node, DOT_FILE);

	if (from_node == 0 || to_node == 0)
		return 0;
	draw_relationship(from_node, to_node);
	return 0;
}

int draw_relationship(const tree from_node, const tree to_node) {
	
	bool isattred = false;
	char *attrbuf[10];
	int attrpos = 0;
	fprintf(DOT_FILE, "%s->%s ", to_node->attr.name, from_node->attr.name);
	if (from_node->class_attr._access != _private) {
		isattred = true;
		attrbuf[attrpos++] = const_cast<char*>( (from_node->class_attr._access == _public ? "color=green" : "color=yellow"));
	}
	else {
		attrbuf[attrpos++] = const_cast<char *>("color=red");
	}
	
	if (from_node->class_attr._virtual == _TRUE) {
		isattred = true;
		attrbuf[attrpos++] = const_cast<char*> ("style=dotted");
	}

	/* latter output these attrbutes to the DOT_FILE stream  */
	fprintf(DOT_FILE, "[");
	for (int i = --attrpos; i >= 0; i--) {
		if (attrbuf[i] == 0)
			continue;
		fprintf(DOT_FILE, "%s,", attrbuf[i]);
	}
	
	fprintf(DOT_FILE, "];\n");
	return 0;
}

int adorn_node(tree node) {
	if (!node)
		return 0;
	fprintf(DOT_FILE,"%s ",
		       (node->attr.name)? node->attr.name : "__no_name__");
	fprintf(DOT_FILE, "[shape=box]");
	return 0;
}
